#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,a,b) for(register int i = (a);i <= (b);++i)
#define per(i,a,b) for(register int i = (a);i >= (b);--i)  
typedef long long ll;
typedef unsigned long long ull;
using std::string;using std::cin;using std::cout;

const int N = 1e6+10;
int n,m,a[N],tot,version,opt,p,x;

struct node{
    int l,r,num;
    node * ls , * rs;
}Tree[20*N],*root[2*N];

inline node * create(){return &Tree[++tot];}

inline void build(node * cur,int L,int R){
    cur->l = L , cur->r = R;
    if(L == R){
        cur->num = a[L];
        return;
    }
    int mid = (L+R)>>1;
    cur->ls = create() , cur->rs = create();
    build(cur->ls,L,mid) , build(cur->rs,mid+1,R);
    return;
}

inline node * upd(node * cur,int L,int R){
    node * now = create();
    now->ls = cur->ls , now->rs = cur->rs , now->l = cur->l , now->r = cur->r;
    int mid = (L+R)>>1;
    if(L == R) now->num = x;
    else if(p <= mid) now->ls = upd(now->ls,L,mid);
    else now->rs = upd(now->rs,mid+1,R);
    return now;
}

inline int query(node * cur){
    int mid = (cur->l + cur->r) >> 1;
    if(cur->l == cur->r) return cur->num; 
    else if(p <= mid) return query(cur->ls);
    else return query(cur->rs); 
}

int main(){
    std::ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    //freopen("in.in", "r", stdin);
    cin >> n >> m;
    rep(i,1,n) cin >> a[i];
    root[0] = create();
    build(root[0],1,n);
    rep(i,1,m){ 
        cin >> version >> opt >> p;
        if(opt&1){ // 改点
            cin >> x;
            root[i] = upd(root[version],1,n);
        } else { // 查询
            cout << query(root[version]) << "\n";
            root[i] = root[version];
        }

    }
    return 0;
}